﻿using HPSocket.WebSocket;
using HPSocket;
using IntelligentGateway.Tools;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace IntelligentGateway.Services
{
    public delegate void MessageProcess(IntPtr intPtr, byte[] Response);
    public delegate void WebsocketClose(IntPtr intPtr);
    public class TPWebsocketServer
    {
        WebSocketServer _websocketServer = null;

        public TPWebsocketServer(string host)
        {
            _websocketServer = new WebSocketServer($"{host}");
            _websocketServer.PingInterval = 30000;
            //try
            //{
            //    _websocketServer.SslConfiguration = new SslConfiguration
            //    {
            //        FromMemory = false,
            //        VerifyMode = SslVerifyMode.Peer,
            //        //CaPemCertFileOrPath = "c:\\ssl\\cps.hzfxmc.com_bundle.crt",
            //        //PemCertFile = "c:\\ssl\\cps.hzfxmc.com_bundle.pem",
            //        //PemKeyFile = "c:\\ssl\\cps.hzfxmc.com.key",
            //        //KeyPassword = ""
            //        CaPemCertFileOrPath = "d:\\ssl\\ca.crt",
            //        PemCertFile = "d:\\ssl\\server.cer",
            //        PemKeyFile = "d:\\ssl\\server.key",
            //        KeyPassword = "123456"
            //    };
            //}
            //catch (Exception ex)
            //{
            //    Log.Error("sslconfiguration:" + ex.ToString());
            //}
            _websocketServer.AddHub<CompassHub>("/");
        }
        public ConcurrentDictionary<int, IntPtr> ConnIDs
        {
            get
            {
                CompassHub hub = _websocketServer.GetHub<CompassHub>("/");
                if (hub != null)
                {
                    return hub.ConnIDs;
                }
                return null;
            }
        }
        public void Close(IntPtr intptr)
        {
            _websocketServer.Close(intptr);
        }
        public ConcurrentDictionary<int, IntPtr> WechatConnIDs
        {
            get
            {
                CompassHub hub = _websocketServer.GetHub<CompassHub>("/");
                if (hub != null)
                {
                    return hub.WechatConnIDs;
                }
                return null;
            }
        }
        public bool Start()
        {
            bool success = _websocketServer.Start();
#if DEBUG
            Log.Debug("WebsocketServer:" + success);
#endif
            return success;
        }
        public CompassHub CompassHub
        {
            get
            {
                return _websocketServer.GetHub<CompassHub>("/");
            }
        }
        public bool SendData(IntPtr ConnID, byte[] Data, int Length)
        {
            bool success = _websocketServer.Send(ConnID, HPSocket.WebSocket.OpCode.Text, Data, Length);
            return success;
        }
        public bool Stop() { return _websocketServer.Stop(); }

    }
    public class CompassHub : IHub
    {
        private ConcurrentDictionary<int, IntPtr> _connIDs = new ConcurrentDictionary<int, IntPtr>();
        ConcurrentDictionary<int, IntPtr> _wechatConnIDs = new ConcurrentDictionary<int, IntPtr>();
        public event MessageProcess MessageProcessEvent;
        public event WebsocketClose WebsocketClose;
        // CompassWebSocketPacket _compassWebsocketPacket = CompassWebSocketPacket.GetSingleton();
        public ConcurrentDictionary<int, IntPtr> ConnIDs
        {
            get { return _connIDs; }
        }
        public ConcurrentDictionary<int, IntPtr> WechatConnIDs
        {
            get { return _wechatConnIDs; }
        }
        public HandleResult OnClose(IWebSocketServer sender, IntPtr connId, SocketOperation socketOperation, int errorCode)
        {
#if DEBUG
            Console.WriteLine($"OnClose:{connId},socketoperation:{socketOperation},errorCode:{errorCode}");
            Log.Debug($"OnClose:{connId},socketoperation:{socketOperation},errorCode:{errorCode}");
#endif         
            if (WebsocketClose != null)
            {
                WebsocketClose(connId);
            }
            GlobalVariables.TPWebSocketIntPtrs.Remove(connId);
            return HandleResult.Ok;
        }

        public HandleResult OnMessage(IWebSocketServer sender, IntPtr connId, bool final, HPSocket.WebSocket.OpCode opCode, byte[] mask, byte[] data)
        {
#if DEBUG
            Console.WriteLine($"OnMessage:{connId},OpCode:{opCode},mask:{string.Join(',', mask)},data:{System.Text.Encoding.UTF8.GetString(data)}");
            Log.Debug($"OnMessage:{connId},OpCode:{opCode},mask:{string.Join(',', mask)},data:{System.Text.Encoding.UTF8.GetString(data)}");
#endif  
            if (MessageProcessEvent != null) MessageProcessEvent(connId, data);
            return HandleResult.Ok;
        }
        public HandleResult OnOpen(IWebSocketServer sender, IntPtr connId)
        {
#if DEBUG
            Console.WriteLine($"OnOpen:{connId}");
            Log.Debug($"OnOpen:{connId}");
#endif
            GlobalVariables.TPWebSocketIntPtrs.Add( connId );
            return HandleResult.Ok;
        }
        public void OnPing(IWebSocketServer sender, IntPtr connId, byte[] data)
        {
#if DEBUG
            Console.WriteLine($"OnPing:{connId},data:{System.Text.Encoding.UTF8.GetString(data)}");
            Log.Debug($"OnPing:{connId},data:{System.Text.Encoding.UTF8.GetString(data)}");
#endif
        }

        public void OnPong(IWebSocketServer sender, IntPtr connId, byte[] data)
        {
#if DEBUG
            Console.WriteLine($"OnPong:{connId},data:{System.Text.Encoding.UTF8.GetString(data)}");
            Log.Debug($"OnPong:{connId},data:{System.Text.Encoding.UTF8.GetString(data)}");
#endif
            //string result = Encoding.UTF8.GetString(data);
            //if(string.IsNullOrEmpty(result)) return;
            //Console.WriteLine("server onpong:"+result);
            //PongMessage message = JsonConvert.DeserializeObject<PongMessage>(result);
            //if(message.Type.Equals("Client"))
            //{
            //    string decrypt = SecureTools.Decrypt(message.Data.ToString());
            //    if (!string.IsNullOrEmpty(decrypt))
            //    {
            //        int projectID = int.Parse(decrypt);
            //        if (projectID > 0)
            //        {
            //            _connIDs.AddOrUpdate(projectID, connId, (p, i) => { i = connId; return i; });
            //        }
            //    }
            //}
            //else if(message.Type.Equals("Wechat"))
            //{
            //    string strRequestID = CommTools.FromBase64String(message.Data.ToString());
            //    if (!string.IsNullOrEmpty(strRequestID))
            //    {
            //        string[] strContent = strRequestID.Split("-");
            //        bool success = int.TryParse(strContent[2], out int RequestID);
            //        if (success)
            //        {
            //            _wechatConnIDs.AddOrUpdate(RequestID, connId, (p, i) => { i = connId; return i; });
            //        }
            //    }

            //}
            //Console.WriteLine($"OnPong:{connId},data:{result}");            
        }
    }
}
